import 'dart:convert';
import 'dart:io';
import 'dart:typed_data';
import 'package:convert/convert.dart';
import 'package:crypto/crypto.dart';
import 'package:logger/logger.dart';

const int partSize = 1024 * 1024 * 3; //默认3m每块

final _logger = Logger(printer: PrettyPrinter(),);

String generateMd5(String data) {
  var content = new Utf8Encoder().convert(data);
  var digest = md5.convert(content);
  // 这里其实就是 digest.toString()
  return base64Encode(digest.bytes);
}

String generateSha512(String input) {
  var content = utf8.encode(input);
  var digest = sha512.convert(content);
  return digest.toString();
}

String fileSha512(String path) {
  File file = File(path);

  int fileSize = file.lengthSync();
  int totalPart = (fileSize * 1.0 / partSize).ceil();

  int start;            //开始读文件的位置
  int length;           //读取文件的长度
  var output = AccumulatorSink<Digest>();
  var input = sha512.startChunkedConversion(output);

  RandomAccessFile raf = file.openSync(mode: FileMode.read);

  try {
    int currentPart = 0;
    while (currentPart < totalPart) {
      start = currentPart * partSize;
      length = (start + partSize > fileSize) ? (fileSize - start ) : partSize;

      Uint8List data = raf.readSync(length);
      input.add(data);
      currentPart++;
    }
  } catch (error, stackTrace) {
    _logger.e('file md5', error: error, stackTrace: stackTrace);
  } finally {
    raf.closeSync();
    input.close();
  }

  var digest = output.events.single.toString();
  return digest;
}

String fileMd5(String path) {
  File file = File(path);

  int fileSize = file.lengthSync();
  int totalPart = (fileSize * 1.0 / partSize).ceil();

  int start;            //开始读文件的位置
  int length;           //读取文件的长度
  var output = AccumulatorSink<Digest>();
  var input = md5.startChunkedConversion(output);

  RandomAccessFile raf = file.openSync(mode: FileMode.read);

  try {
    int currentPart = 0;
    while (currentPart < totalPart) {
      start = currentPart * partSize;
      length = (start + partSize > fileSize) ? (fileSize - start ) : partSize;

      Uint8List data = raf.readSync(length);
      input.add(data);
      currentPart++;
    }
  } catch (error, stackTrace) {
    _logger.e('file md5', error: error, stackTrace: stackTrace);
  } finally {
    raf.closeSync();
    input.close();
  }

  var digest = output.events.single.toString();
  return digest;
}